home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / Mac OS USB DDK / Examples / USBTabletModule / USBTabletModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-10  |  11.2 KB  |  323 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        USBTabletModule.c
  3.  
  4.     Contains:    HID Module for USB Wacom
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12.  
  13. #include <Types.h>
  14. #include <Devices.h>
  15. #include <processes.h>
  16. #include <DriverServices.h>
  17. #include <USB.h>
  18.  
  19. #include "USBTabletModule.h"
  20.  
  21. usbWacomPBStruct myWacomPB;
  22.  
  23. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  24. {
  25.     paramblock->usbReference = theDeviceRef;
  26.     paramblock->pbVersion = kUSBCurrentPBVersion;
  27.     paramblock->usbStatus = noErr;
  28.     paramblock->usbBuffer = nil;        
  29.     paramblock->usbActCount = 0;
  30.     paramblock->usbReqCount = 0;
  31.     paramblock->usbFlags = 0;
  32.     paramblock->usbOther = 0;
  33. }
  34.  
  35.  
  36.  
  37. Boolean immediateError(OSStatus err)
  38. {
  39.     return((err != kUSBPending) && (err != noErr) );
  40. }
  41.  
  42. void InitiateTransactionProc(USBPB *pb)
  43. {
  44. register usbWacomPBStruct *pWacomPB;
  45. OSStatus myErr;
  46.  
  47.     pWacomPB = (usbWacomPBStruct *)(pb);
  48.     pWacomPB->transDepth++;
  49.     if (pWacomPB->transDepth < 0)
  50.     {
  51.         USBExpertFatalError(pWacomPB->deviceRef, kUSBInternalErr, "\pWacom Driver: transDepth < 0 (initiation)", pWacomPB->pb.usbRefcon );
  52.     }
  53.     
  54.     if (pWacomPB->transDepth > 1)
  55.     {
  56.         USBExpertFatalError(pWacomPB->deviceRef, kUSBInternalErr, "\pWacom Driver: transDepth > 1 (initiation)", pWacomPB->pb.usbRefcon );
  57.     }
  58.     
  59.     switch(pWacomPB->pb.usbRefcon & ~kRetryTransaction)
  60.     {
  61.         case kFindInterface:
  62.             InitParamBlock(pWacomPB->deviceRef, &pWacomPB->pb);
  63.             pWacomPB->pb.usb.cntl.WIndex = 0;
  64.             pWacomPB->pb.usb.cntl.WValue = 0;
  65.             pWacomPB->pb.usbClassType = kUSBHIDInterfaceClass;
  66.             pWacomPB->pb.usbSubclass = kUSBBootInterfaceSubClass;
  67.             pWacomPB->pb.usbProtocol = kUSBMouseInterfaceProtocol;
  68.             pWacomPB->pb.usbRefcon |= kCompletionPending;
  69.             pWacomPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  70.             myErr = USBFindNextInterface(pb);
  71.             if(immediateError(myErr))
  72.             {
  73.                 USBExpertFatalError(pWacomPB->pb.usbReference, kUSBInternalErr, "\pWacom Driver: USBFindNextInterface (immediate error)", myErr);
  74.                 pWacomPB->pb.usbRefcon = kReturnFromDriver;
  75.             }
  76.             break;
  77.             
  78.         case kOpenDevice:
  79.             InitParamBlock(pWacomPB->deviceRef, &pWacomPB->pb);
  80.             pWacomPB->pb.usb.cntl.WValue = pWacomPB->configurationNumber;
  81.             pWacomPB->pb.usbRefcon |= kCompletionPending;
  82.             
  83.             pWacomPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  84.             myErr = USBOpenDevice(pb);
  85.             if(immediateError(myErr))
  86.             {
  87.                 USBExpertFatalError(pWacomPB->pb.usbReference, kUSBInternalErr, "\pWacom Driver: USBOpenDevice (immediate error)", myErr);
  88.                 pWacomPB->pb.usbRefcon = kReturnFromDriver;
  89.             }
  90.             break;
  91.             
  92.         case kNewInterfaceRef:
  93.             InitParamBlock(pWacomPB->deviceRef, &pWacomPB->pb);
  94.             pWacomPB->pb.usb.cntl.WIndex = pWacomPB->interfaceNumber;
  95.             pWacomPB->pb.usbRefcon |= kCompletionPending;
  96.             
  97.             pWacomPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  98.             myErr = USBNewInterfaceRef(pb);
  99.             if(immediateError(myErr))
  100.             {
  101.                 USBExpertFatalError(pWacomPB->pb.usbReference, kUSBInternalErr, "\pWacom Driver: USBNewInterfaceRef (immediate error)", myErr);
  102.                 pWacomPB->pb.usbRefcon = kReturnFromDriver;
  103.             }
  104.             break;
  105.             
  106.         case kConfigureInterface:
  107.             InitParamBlock(pWacomPB->interfaceRef, &pWacomPB->pb);
  108.             pWacomPB->pb.usbRefcon |= kCompletionPending;
  109.             
  110.             pWacomPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  111.             myErr = USBConfigureInterface(pb);
  112.             if(immediateError(myErr))
  113.             {
  114.                 USBExpertFatalError(pWacomPB->pb.usbReference, kUSBInternalErr, "\pWacom Driver: USBConfigureInterface (immediate error)", myErr);
  115.                 pWacomPB->pb.usbRefcon = kReturnFromDriver;
  116.             }
  117.             break;
  118.             
  119.         case kSetProtocol:
  120.             InitParamBlock(pWacomPB->interfaceRef, &pWacomPB->pb);
  121.             
  122.             pWacomPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  123.             pWacomPB->pb.usb.cntl.BRequest = kHIDRqSetProtocol;
  124.             pWacomPB->pb.usb.cntl.WValue = kHIDReportProtocolValue; 
  125.             pWacomPB->pb.usb.cntl.WIndex = pWacomPB->interfaceNumber;
  126.             pWacomPB->pb.usbRefcon |= kCompletionPending;
  127.             
  128.             pWacomPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  129.             myErr = USBDeviceRequest(&pWacomPB->pb);
  130.             if (immediateError(myErr))
  131.             {
  132.                 USBExpertFatalError(pWacomPB->deviceRef, kUSBInternalErr, "\pWacom Driver: kHIDRqSetProtocol (immediate error)", myErr);
  133.                 pWacomPB->pb.usbRefcon = kReturnFromDriver;
  134.             }
  135.             break;
  136.             
  137.         case kGetReportDescriptor:
  138.             InitParamBlock(pWacomPB->deviceRef, &pWacomPB->pb);
  139.             pWacomPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBInterface);
  140.             pWacomPB->pb.usb.cntl.BRequest = kUSBRqGetDescriptor;
  141.             pWacomPB->pb.usb.cntl.WValue = (0x22 << 8) + 1;             // get the first report descriptor
  142.             pWacomPB->pb.usb.cntl.WIndex = pWacomPB->interfaceNumber;
  143.             pWacomPB->pb.usbReqCount = 0x66;
  144.             pWacomPB->pb.usbBuffer = pWacomPB->hidReportDescriptor;
  145.             
  146.             pWacomPB->pb.usbRefcon |= kCompletionPending;
  147.             pWacomPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  148.             myErr = USBDeviceRequest(pb);
  149.             if(immediateError(myErr))
  150.             {
  151.                 USBExpertFatalError(pWacomPB->pb.usbReference, kUSBInternalErr, "\pWacom Driver: kGetReportDescriptor - immediate error", myErr);
  152.             }
  153.             break;
  154.         
  155.         case kFindInterruptPipe:
  156.             InitParamBlock(pWacomPB->interfaceRef, &pWacomPB->pb);
  157.             pWacomPB->pb.usbFlags = kUSBIn;
  158.             pWacomPB->pb.usbClassType = kUSBInterrupt; 
  159.             
  160.             pWacomPB->pb.usbRefcon |= kCompletionPending;
  161.             pWacomPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  162.             myErr = USBFindNextPipe(&pWacomPB->pb);
  163.             if (immediateError(myErr))
  164.             {
  165.                 USBExpertFatalError(pWacomPB->deviceRef, kUSBInternalErr, "\pWacom Driver: kFindInterruptPipe (immediate error)", myErr);
  166.                 pWacomPB->pb.usbRefcon = kReturnFromDriver;
  167.             }
  168.             break;
  169.             
  170.         case kReadInterruptPipe:
  171.             InitParamBlock(pWacomPB->pipeRef, &pWacomPB->pb);
  172.  
  173.             pWacomPB->pb.usbBuffer = (Ptr)pWacomPB->hidReport;
  174.             pWacomPB->pb.usbReqCount = 7;
  175.             pWacomPB->pb.usb.cntl.WIndex = pWacomPB->interfaceNumber;    
  176.             
  177.             pWacomPB->pb.usbRefcon |= kCompletionPending;
  178.             pWacomPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  179.             myErr = USBIntRead(&pWacomPB->pb);
  180.             if(immediateError(myErr))
  181.             {
  182.                 USBExpertFatalError(pWacomPB->deviceRef, kUSBInternalErr, "\pWacom Driver: kReadInterruptPipe (ImmediateError)", myErr);
  183.             }
  184.             break;
  185.             
  186.         default:
  187.             USBExpertFatalError(pWacomPB->deviceRef, kUSBInternalErr, "\pWacom Driver: Transaction initiated with bad refcon value", pWacomPB->pb.usbRefcon);
  188.             pWacomPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  189.             break;
  190.     }
  191.     
  192. // At this point the control is returned to the system.  If a USB transaction
  193. // has been initiated, then it will call the Complete procs
  194. // (below) to handle the results of the transaction.
  195. }
  196.  
  197.  
  198. void TransactionCompletionProc(USBPB *pb)
  199. {
  200. register usbWacomPBStruct *pWacomPB;
  201. unsigned char    * errstring;
  202. USBPipeState     pipeState;
  203.  
  204.     pWacomPB = (usbWacomPBStruct *)(pb);
  205.     pWacomPB->transDepth--;
  206.     if (pWacomPB->transDepth < 0)
  207.     {
  208.         USBExpertFatalError(pWacomPB->deviceRef, kUSBInternalErr, "\pWacom Driver: transDepth < 0 (completion)", pWacomPB->pb.usbRefcon );
  209.     }
  210.     
  211.     if (pWacomPB->transDepth > 1)
  212.     {
  213.         USBExpertFatalError(pWacomPB->deviceRef, kUSBInternalErr, "\pWacom Driver: transDepth > 1 (completion)", pWacomPB->pb.usbRefcon );
  214.     }
  215.     
  216.     if(pWacomPB->pb.usbStatus != noErr)                                                        // was there an error?
  217.     {
  218.         switch(pWacomPB->pb.usbRefcon & 0x0fff)                                                // yes, so show where the error occurred
  219.         {
  220.             case kFindInterface:                  errstring = "\pWacom Driver: Error during kFindInterface"; break;
  221.             case kOpenDevice:                    errstring = "\pWacom Driver: Error during kOpenDevice"; break;
  222.             case kNewInterfaceRef:                errstring = "\pWacom Driver: Error during kNewInterfaceRef"; break;
  223.             case kConfigureInterface:              errstring = "\pWacom Driver: Error during kConfigureInterface"; break;
  224.             case kSetProtocol:                      errstring = "\pWacom Driver: Error during kSetProtocol"; break;
  225.             case kGetReportDescriptor:              errstring = "\pWacom Driver: Error during kGetReportDescriptor"; break;
  226.             case kFindInterruptPipe:              errstring = "\pWacom Driver: Error during kFindInterruptPipe"; break;
  227.             case kReadInterruptPipe:              errstring = "\pWacom Driver: Error during kReadInterruptPipe"; break;
  228.             default:                              errstring = "\pWacom Driver: Error occurred, but state is unknown"; break;
  229.         };
  230.         USBExpertFatalError(pWacomPB->deviceRef, pWacomPB->pb.usbStatus, errstring, (pWacomPB->pb.usbRefcon & 0x0fff));
  231.         
  232.         pWacomPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);                // set up to retry the transaction
  233.         pWacomPB->pb.usbRefcon |= kRetryTransaction;
  234.         pWacomPB->retryCount--;
  235.         
  236.         if ((!pWacomPB->retryCount)    || (pWacomPB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  237.         {                                                                                // or received an abort?
  238.             USBExpertStatus(pWacomPB->deviceRef, "\pWacom Driver: Pipe abort or unable to recover from error", pWacomPB->deviceRef);
  239.             pWacomPB->pb.usbRefcon = kReturnFromDriver;                                    // if so, just exit.
  240.         }
  241.         else                                                                            // if it didn't abort and there's retries left, then...
  242.         {
  243.             if (pWacomPB->pipeRef)                                                        // check if the pipe is open.
  244.             {
  245.                 USBGetPipeStatusByReference(pWacomPB->pipeRef, &pipeState);                // yes, so what it's state?
  246.                 if (pipeState != kUSBActive)                                            // if it's not active, try to clear it.  It might be stalled...
  247.                 {
  248.                     USBExpertStatus(pWacomPB->deviceRef, "\pWacom Driver: Pipe is open and stalled, clearing stall...", pWacomPB->deviceRef);
  249.                     USBClearPipeStallByReference(pWacomPB->pipeRef);
  250.                 }
  251.             }
  252.         }
  253.     }
  254.     else
  255.     {
  256.         pWacomPB->pb.usbRefcon &= ~kRetryTransaction;
  257.         pWacomPB->retryCount = kWacomRetryCount;
  258.     }
  259.  
  260.     if (pWacomPB->pb.usbRefcon & kCompletionPending)             
  261.     {                                                
  262.         pWacomPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  263.         switch(pWacomPB->pb.usbRefcon)
  264.         {
  265.             case kFindInterface:
  266.                 if ((pWacomPB->pb.usbClassType == kUSBHIDInterfaceClass) && 
  267.                     (pWacomPB->pb.usbSubclass == kUSBBootInterfaceSubClass) &&
  268.                     (pWacomPB->pb.usbProtocol == kUSBMouseInterfaceProtocol))
  269.                 {
  270.                     pWacomPB->pb.usbRefcon = kOpenDevice;
  271.                     pWacomPB->interfaceNumber = pWacomPB->pb.usb.cntl.WIndex;
  272.                     pWacomPB->configurationNumber = pWacomPB->pb.usb.cntl.WValue;
  273.                 }
  274.                 else
  275.                 {
  276.                     pWacomPB->pb.usbRefcon = kReturnFromDriver;
  277.                 }
  278.                 break;
  279.                 
  280.             case kOpenDevice:
  281.                 pWacomPB->pb.usbRefcon = kNewInterfaceRef;
  282.                 break;
  283.                 
  284.             case kNewInterfaceRef:
  285.                 pWacomPB->interfaceRef = pWacomPB->pb.usbReference;
  286.                 pWacomPB->pb.usbRefcon = kConfigureInterface;
  287.                 break;
  288.             
  289.             case kConfigureInterface:
  290.                 pWacomPB->pb.usbRefcon = kGetReportDescriptor;
  291.                 break;
  292.             
  293.             case kGetReportDescriptor:
  294.                 pWacomPB->pb.usbRefcon = kFindInterruptPipe;
  295.                 break;
  296.                 
  297.             case kFindInterruptPipe:
  298.                 if ((pWacomPB->pb.usbClassType == kUSBInterrupt) && 
  299.                     (pWacomPB->pb.usbFlags == kUSBIn))
  300.                 {
  301.                     pWacomPB->hidReportSize = pWacomPB->pb.usb.cntl.WValue;
  302.                     pWacomPB->pipeRef = pWacomPB->pb.usbReference;
  303.                     pWacomPB->pb.usbRefcon = kReadInterruptPipe;
  304.                 }
  305.                 else
  306.                 {
  307.                     pWacomPB->pb.usbRefcon = kReturnFromDriver;
  308.                 }
  309.                 break;
  310.                 
  311.             case kReadInterruptPipe:
  312.                 //DebugStr("\pWacom read completed");
  313.                 ProcessInterruptReport(pWacomPB->refcon, pWacomPB->hidReport);
  314.                 pWacomPB->pb.usbRefcon = kReadInterruptPipe;
  315.                 break;
  316.  
  317.         }
  318.     }
  319.     if (!(pWacomPB->pb.usbRefcon & kReturnFromDriver))
  320.         InitiateTransactionProc(pb);
  321. }
  322.  
  323.